package com.sds.sweng.swat.miplatform.service.layouts;

import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Layout;
import org.eclipse.swt.widgets.Scrollable;


public class ValidationViewerLayout extends Layout {

 	private int marginWidth = 0;

 	private int marginHeight = 0;

 	private int spacing = 0;

	protected Point computeSize (Composite composite, int wHint, int hHint, boolean flushCache) {
		Control [] children = composite.getChildren ();
		int count = children.length;
		int maxWidth = 0, maxHeight = 0;

		int width = 0, height = 0, childHeight = 0;

		for (int i=0; i<count; i++) {
			Control child = children [i];
			int w = wHint, h = hHint;
			if (count > 0) {
				if (hHint != SWT.DEFAULT) {
					h = Math.max (0, (hHint - (count - 1) * spacing) / count);
				}
			}
			Point size = computeChildSize (child, w, h, flushCache);

			maxWidth = Math.max (maxWidth, size.x);
			//maxHeight = Math.max (maxHeight, size.y);
			childHeight = Math.max(size.y, child.getSize().y);
			child.setSize(maxWidth, childHeight);

			height += childHeight;
		}

		width = maxWidth;
		//height = count * maxHeight;

		if (count != 0) height += (count - 1) * spacing;

		width += marginWidth * 2;
		height += marginHeight * 2;
		if (wHint != SWT.DEFAULT) width = wHint;
		if (hHint != SWT.DEFAULT) height = hHint;
		return new Point (width, height);
	}

	Point computeChildSize (Control control, int wHint, int hHint, boolean flushCache) {
		FillData data = (FillData)control.getLayoutData ();
		if (data == null) {
			data = new FillData ();
			control.setLayoutData (data);
		}
		Point size = null;
		if (wHint == SWT.DEFAULT && hHint == SWT.DEFAULT) {
			size = data.computeSize (control, wHint, hHint, flushCache);
		} else {
			// TEMPORARY CODE
			int trimX, trimY;
			if (control instanceof Scrollable) {
				Rectangle rect = ((Scrollable) control).computeTrim (0, 0, 0, 0);
				trimX = rect.width;
				trimY = rect.height;
			} else {
				trimX = trimY = control.getBorderWidth () * 2;
			}
			int w = wHint == SWT.DEFAULT ? wHint : Math.max (0, wHint - trimX);
			int h = hHint == SWT.DEFAULT ? hHint : Math.max (0, hHint - trimY);
			size = data.computeSize (control, w, h, flushCache);
		}
		return size;
	}

	protected boolean flushCache (Control control) {
		Object data = control.getLayoutData();
		if (data != null) ((FillData)data).flushCache();
		return true;
	}

	String getName () {
		String string = getClass ().getName ();
		int index = string.lastIndexOf ('.');
		if (index == -1) return string;
		return string.substring (index + 1, string.length ());
	}

	protected void layout (Composite composite, boolean flushCache) {
		Rectangle rect = composite.getClientArea ();
		Control [] children = composite.getChildren ();
		int count = children.length;
		if (count == 0) return;
		int width = rect.width - marginWidth * 2;
		int height = rect.height - marginHeight * 2;

		height -= (count - 1) * spacing;
		int x = rect.x + marginWidth, cellHeight = height / count;
		int y = rect.y + marginHeight, extra = height % count;
		for (int i=0; i<count; i++) {
			Control child = children [i];
			//int childHeight = cellHeight;
			int childHeight = child.getSize().y;
			if (i == 0) {
				childHeight += extra / 2;
			} else {
				if (i == count - 1) childHeight += (extra + 1) / 2;
			}
			child.setBounds (x, y, width, childHeight);
			y += childHeight + spacing;
		}
	}

	/**
	 * Returns a string containing a concise, human-readable
	 * description of the receiver.
	 *
	 * @return a string representation of the layout
	 */
	public String toString () {
	 	String string = getName ()+" {";
	 	string += "type=SWT.HORIZONTAL ";
	 	if (marginWidth != 0) string += "marginWidth="+marginWidth+" ";
	 	if (marginHeight != 0) string += "marginHeight="+marginHeight+" ";
	 	if (spacing != 0) string += "spacing="+spacing+" ";
	 	string = string.trim();
	 	string += "}";
	 	return string;
	}
}

class FillData {

	int defaultWidth = -1, defaultHeight = -1;
	int currentWhint, currentHhint, currentWidth = -1, currentHeight = -1;

	Point computeSize (Control control, int wHint, int hHint, boolean flushCache) {
		if (flushCache) flushCache();
		if (wHint == SWT.DEFAULT && hHint == SWT.DEFAULT) {
			if (defaultWidth == -1 || defaultHeight == -1) {
				Point size = control.computeSize (wHint, hHint, flushCache);
				defaultWidth = size.x;
				defaultHeight = size.y;
			}
			return new Point(defaultWidth, defaultHeight);
		}
		if (currentWidth == -1 || currentHeight == -1 || wHint != currentWhint || hHint != currentHhint) {
			Point size = control.computeSize (wHint, hHint, flushCache);
			currentWhint = wHint;
			currentHhint = hHint;
			currentWidth = size.x;
			currentHeight = size.y;
		}
		return new Point(currentWidth, currentHeight);
	}

	void flushCache () {
		defaultWidth = defaultHeight = -1;
		currentWidth = currentHeight = -1;
	}
}
